`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    22:51:41 08/04/2013 
// Design Name: 
// Module Name:    BoardInterface 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module BoardInterface
	#(parameter cpuCount = 1,
	 parameter memoryCount = 1)
	(input clk, input clk_50, input reset,
	output [1:0] mode, input modeSwitch,
	output [cpuCount-1:0] debug_cpu_clks,
	input EppAstb, input EppDstb, input EppWR, output EppWait, inout [7:0] EppDB,
	 output [3:0] memorySelector, input [31:0] memorySelectedSize, output [31:0] memoryAddress, input [31:0] memoryDataIn, input memoryDataDone, output [31:0] memoryDataOut, output memoryWrite,
	 output [3:0] cpuSelector, input [7:0] cpuStandardclk, input  [31:0] cpuPC, output [4:0] cpuRegisterSelector, input [31:0] cpuRegisterValue);
	 
	 
	 
	 //Mode switcher
	reg [1:0] modeReg = 2'b0;
	assign mode = modeReg;
	
	//should be changed when PC is allowed to change mode
	wire mode_override_enable;
	wire [1:0] mode_override;
	
	reg btnHeld;
	
	reg [27:0] counter;
	always @(posedge clk_50) begin
		if(mode_override_enable) begin
			modeReg <= mode_override;
			counter <= 0;
			btnHeld <= 0;
			end
		else if(modeSwitch || (~btnHeld & counter >= 28'd1000000) ) begin
			if(counter >= 28'd70000000 || (~btnHeld & counter >= 28'd1000000) ) begin
				case(modeReg)
					2'b00: modeReg <= 2'b01;
					2'b01: modeReg <= 2'b11;
					2'b10: modeReg <= 2'b11;
					2'b11: modeReg <= 2'b00;
				endcase
				counter <= 0;
				btnHeld <= 1;
			end
			else begin
				modeReg <= modeReg;
				counter <= counter + 1;
			end
		end
		else
		begin
			btnHeld <= 0;
			modeReg <= modeReg;
			counter <= 0;
		end
	end
	
	

	 
	 //FSM	 
	 wire [7:0] dataIn;
	 wire dataInReady;
	 wire dataInAck;
	 
	
	 wire [7:0] dataOut;
	 wire dataOutReady;
	 wire dataOutAck;
	 
	 DEPPReaderWriter myReadWrite(clk_50, reset, ~EppAstb, ~EppDstb, ~EppWR, EppWait, EppDB,
	 dataIn, dataInReady, dataInAck, dataOut, dataOutReady, dataOutAck);
	 
	 
	 reg [7:0] state, nextState, stateAfterReg;
	 
	 
	 reg [31:0] tempWord;
	
	 
	 parameter OPERATION_NA = 4'd0;
	 parameter OPERATION_NA2 = 4'd15;
	 parameter OPERATION_UPLOAD_CONFIG = 4'd1;
	 parameter OPERATION_DOWN_MEMORY = 4'd2;
	 parameter OPERATION_UPLOAD_MEMORY = 4'd3;
	 parameter OPERATION_BOARD_CONTROL = 4'd4;
	 parameter OPERATION_DEBUG1 = 4'd5;
	 
	 
	 parameter OPERATION_TEST_BOARD = 4'd14;
	 
	 //OPERATION_NA_STATES
	 parameter STATE_NA_IDLE = {OPERATION_NA, 4'b0};
	 parameter STATE_NA_READ1 = {OPERATION_NA, 4'd1};
	 parameter STATE_NA_READ2 = {OPERATION_NA, 4'd2};
	 parameter STATE_NA_READ3 = {OPERATION_NA, 4'd3};
	 parameter STATE_NA_WRITE1 = {OPERATION_NA, 4'd4};
	 parameter STATE_NA_WRITE2 = {OPERATION_NA, 4'd5};
	 parameter STATE_NA_READ_OP1 = {OPERATION_NA, 4'd6};
	 parameter STATE_NA_READ_OP_SUPPORTED = {OPERATION_NA, 4'd7};
	 parameter STATE_NA_READ_OP_NOT_SUPPORTED = {OPERATION_NA, 4'd8};
	 parameter STATE_NA_WRITE_WORD1 = {OPERATION_NA, 4'd9};
	 parameter STATE_NA_WRITE_WORD2 = {OPERATION_NA, 4'd10};
	 parameter STATE_NA_WRITE_WORD3 = {OPERATION_NA, 4'd11};
	 parameter STATE_NA_WRITE_WORD4 = {OPERATION_NA, 4'd12};
	 parameter STATE_NA_READ_WORD1 = {OPERATION_NA, 4'd13};
	 parameter STATE_NA_READ_WORD2 = {OPERATION_NA, 4'd14};
	 parameter STATE_NA_READ_WORD3 = {OPERATION_NA, 4'd15};
	 parameter STATE_NA_READ_WORD4 = {OPERATION_NA2, 4'd1};
	 
	 
	 
	 //OPERATION_UPLOAD_CONFIG
	 parameter STATE_UPCO_S1 = {OPERATION_UPLOAD_CONFIG, 4'd0};
	 parameter STATE_UPCO_S2 = {OPERATION_UPLOAD_CONFIG, 4'd1};
	 parameter STATE_UPCO_S3 = {OPERATION_UPLOAD_CONFIG, 4'd2};
	 parameter STATE_UPCO_S4 = {OPERATION_UPLOAD_CONFIG, 4'd3};
	 parameter STATE_UPCO_S5 = {OPERATION_UPLOAD_CONFIG, 4'd4};
	 parameter STATE_UPCO_S6 = {OPERATION_UPLOAD_CONFIG, 4'd5};
	 parameter STATE_UPCO_S7 = {OPERATION_UPLOAD_CONFIG, 4'd6};
	 
	 //OPERATION_DOWNLOAD_MEMORY
	 parameter STATE_DOWN_S1 = {OPERATION_DOWN_MEMORY, 4'd0};
	 parameter STATE_DOWN_S2 = {OPERATION_DOWN_MEMORY, 4'd1};
	 parameter STATE_DOWN_S3 = {OPERATION_DOWN_MEMORY, 4'd2};
	 parameter STATE_DOWN_ACCEPTED = {OPERATION_DOWN_MEMORY, 4'd3};
	 parameter STATE_DOWN_DENIED = {OPERATION_DOWN_MEMORY, 4'd4};
	 parameter STATE_DOWN_S4 = {OPERATION_DOWN_MEMORY, 4'd5};
	 parameter STATE_DOWN_S5 = {OPERATION_DOWN_MEMORY, 4'd6};
	 parameter STATE_DOWN_S6 = {OPERATION_DOWN_MEMORY, 4'd7};
	 parameter STATE_DOWN_S7 = {OPERATION_DOWN_MEMORY, 4'd8};
	 parameter STATE_DOWN_S8 = {OPERATION_DOWN_MEMORY, 4'd9};
	 
	 
	 //OPERATION_UPLOAD_MEMORY
	 parameter STATE_UPLOAD_S1 = {OPERATION_UPLOAD_MEMORY, 4'd0};
	 parameter STATE_UPLOAD_S2 = {OPERATION_UPLOAD_MEMORY, 4'd1};
	 parameter STATE_UPLOAD_S3 = {OPERATION_UPLOAD_MEMORY, 4'd2};
	 parameter STATE_UPLOAD_S4 = {OPERATION_UPLOAD_MEMORY, 4'd3};
	 parameter STATE_UPLOAD_ACCEPTED = {OPERATION_UPLOAD_MEMORY, 4'd4};
	 parameter STATE_UPLOAD_DENIED = {OPERATION_UPLOAD_MEMORY, 4'd5};
	 parameter STATE_UPLOAD_S5 = {OPERATION_UPLOAD_MEMORY, 4'd6};
	 parameter STATE_UPLOAD_S6 = {OPERATION_UPLOAD_MEMORY, 4'd7};
	 parameter STATE_UPLOAD_S7 = {OPERATION_UPLOAD_MEMORY, 4'd8};
	 parameter STATE_UPLOAD_S8 = {OPERATION_UPLOAD_MEMORY, 4'd9};
	 
	 
	 //OPERATION_BOARD_CONTROL
	 parameter STATE_BOARD_CONTROL_S1 = {OPERATION_BOARD_CONTROL, 4'd0};
	 parameter STATE_BOARD_CONTROL_S2 = {OPERATION_BOARD_CONTROL, 4'd1};
	 parameter STATE_BOARD_CONTROL_CHANGE_MODE1 = {OPERATION_BOARD_CONTROL, 4'd2};
	 parameter STATE_BOARD_CONTROL_CHANGE_MODE2 = {OPERATION_BOARD_CONTROL, 4'd3};
	 parameter STATE_BOARD_CONTROL_CHANGE_MODE3 = {OPERATION_BOARD_CONTROL, 4'd4};
	 parameter STATE_BOARD_CONTROL_READ_MODE1 = {OPERATION_BOARD_CONTROL, 4'd5};
	 
	 //sub operations in board control
	 parameter OP_BC_CHANGE_MODE = 4'd1;
	 parameter OP_BC_READ_MODE = 4'd2;
	 
	 //OPERATION_DEBUGGER
	 parameter STATE_DEBUG1_S1 = {OPERATION_DEBUG1, 4'd0};
	 parameter STATE_DEBUG1_S2 = {OPERATION_DEBUG1, 4'd1};
	 
	 parameter OP_DEBUG1_STEP = 4'd1;
	 parameter OP_DEBUG1_GET_PC = 4'd2;
	 parameter OP_DEBUG1_GET_REGFILE = 4'd3;
	 
	 parameter STATE_DEBUG1_STEP1 = {OPERATION_DEBUG1, 4'd2};
	 parameter STATE_DEBUG1_STEP2 = {OPERATION_DEBUG1, 4'd3};
	 
	 parameter STATE_DEBUG1_GET_PC1 = {OPERATION_DEBUG1, 4'd4};
	 parameter STATE_DEBUG1_GET_PC2 = {OPERATION_DEBUG1, 4'd5};
	 parameter STATE_DEBUG1_GET_PC3 = {OPERATION_DEBUG1, 4'd6};
	 parameter STATE_DEBUG1_GET_PC4 = {OPERATION_DEBUG1, 4'd7};
	 
	 parameter STATE_DEBUG1_GET_REGFILE1 = {OPERATION_DEBUG1, 4'd8};
	 parameter STATE_DEBUG1_GET_REGFILE2 = {OPERATION_DEBUG1, 4'd9};
	 parameter STATE_DEBUG1_GET_REGFILE3 = {OPERATION_DEBUG1, 4'd10};
	 parameter STATE_DEBUG1_GET_REGFILE4 = {OPERATION_DEBUG1, 4'd11};
	 parameter STATE_DEBUG1_GET_REGFILE5 = {OPERATION_DEBUG1, 4'd12};
	 
	 
	 

	 
	 //OPERATION_TEST_BOARD
	 parameter STATE_TEST_S1 = {OPERATION_TEST_BOARD, 4'd0};
	 
	 
	 parameter ACCEPTED_BYTE = 8'b10101111;
	 parameter DECLINED_BYTE = 8'b10100000;
	 
	 
	 wire [3:0] cpuCountBus = cpuCount;
	 wire [3:0] memCountBus = memoryCount;
	 
	 always @(posedge clk_50 or posedge reset) begin
		if(reset)	state <= STATE_NA_IDLE;
		else			state <= nextState;
	 end
	 
	 reg [7:0] tempReg, temp2Reg;
	 reg [31:0] countReg;
	 reg [3:0] selectorReg;
	 
	 reg [31:0] memorySize;
	 
	 reg [15:0] cpuDebugClksReg;
	 
	 assign debug_cpu_clks = cpuDebugClksReg[cpuCount-1:0];
	 
	 reg writeMemReg;
	 
	 assign memoryWrite = writeMemReg;
	 assign cpuRegisterSelector = countReg[4:0];
	 assign cpuSelector = selectorReg;
	 assign memorySelector = selectorReg;
	 //reg [7:0] temp2Reg;
	 
	 //next state logic
	 always @(*) begin
		nextState = state;
		case(state)
			STATE_NA_IDLE: nextState = STATE_NA_READ1;
			STATE_NA_READ1: if(dataInReady) nextState = STATE_NA_READ2;
			STATE_NA_READ2: if(~dataInReady) nextState = STATE_NA_READ3;
			STATE_NA_READ3:  nextState = stateAfterReg;
			STATE_NA_WRITE1: if(dataOutAck) nextState = STATE_NA_WRITE2;
			STATE_NA_WRITE2: if(~dataOutAck) nextState = stateAfterReg;
			STATE_NA_READ_OP1: begin
				if((tempReg[3:0] == OPERATION_UPLOAD_CONFIG) | (tempReg[3:0] == OPERATION_DOWN_MEMORY) | (tempReg[3:0] == OPERATION_UPLOAD_MEMORY) | (tempReg[3:0] == OPERATION_BOARD_CONTROL) | (tempReg[3:0] == OPERATION_DEBUG1)) nextState = STATE_NA_READ_OP_SUPPORTED;
				else													nextState = STATE_NA_READ_OP_NOT_SUPPORTED;
			end
			STATE_NA_READ_OP_SUPPORTED: nextState = STATE_NA_WRITE1;
			STATE_NA_READ_OP_NOT_SUPPORTED: nextState = STATE_NA_WRITE1;
			STATE_UPCO_S1: nextState = STATE_NA_WRITE1;
			STATE_UPCO_S2: nextState = STATE_NA_WRITE1;
			STATE_UPCO_S3: nextState = (selectorReg == cpuCount) ? STATE_UPCO_S4 : STATE_UPCO_S2;
			STATE_UPCO_S4: nextState = STATE_UPCO_S5;
			STATE_UPCO_S5: nextState = STATE_NA_WRITE_WORD1;
			STATE_UPCO_S6: nextState = (selectorReg == memoryCount) ? STATE_NA_IDLE: STATE_UPCO_S5;
			STATE_NA_WRITE_WORD1: nextState = STATE_NA_WRITE1;
			STATE_NA_WRITE_WORD2: nextState = STATE_NA_WRITE1;
			STATE_NA_WRITE_WORD3: nextState = STATE_NA_WRITE1;
			STATE_NA_WRITE_WORD4: nextState = STATE_NA_WRITE1;
			STATE_NA_READ_WORD1: nextState = STATE_NA_READ1;
			STATE_NA_READ_WORD2: nextState = STATE_NA_READ1;
			STATE_NA_READ_WORD3: nextState = STATE_NA_READ1;
			STATE_NA_READ_WORD4: nextState = temp2Reg;
			STATE_DOWN_S1: nextState = STATE_NA_READ1;
			STATE_DOWN_S2: nextState = STATE_NA_READ1;
			STATE_DOWN_S3: nextState = ((memorySelectedSize  >= memorySize) & (selectorReg < memoryCount)) ? STATE_DOWN_ACCEPTED : STATE_DOWN_DENIED;
			STATE_DOWN_ACCEPTED: nextState = STATE_NA_WRITE1;
			STATE_DOWN_DENIED: nextState = STATE_NA_WRITE1;
			STATE_DOWN_S4: nextState = (countReg == memorySize) ? STATE_DOWN_S8 : STATE_NA_READ1;
			STATE_DOWN_S5: nextState = STATE_DOWN_S6;
			STATE_DOWN_S6: nextState = STATE_DOWN_S7;
			STATE_DOWN_S7: nextState = STATE_DOWN_S4;
			STATE_DOWN_S8: nextState = STATE_NA_WRITE1;
			STATE_UPLOAD_S1: nextState = STATE_NA_READ1;
			STATE_UPLOAD_S2: nextState = STATE_NA_READ1;
			STATE_UPLOAD_S3: nextState = STATE_NA_READ1;
			STATE_UPLOAD_S4: nextState = (memorySelectedSize >= memorySize) & (selectorReg < memoryCount) ? STATE_UPLOAD_ACCEPTED : STATE_UPLOAD_DENIED;
			STATE_UPLOAD_ACCEPTED: nextState = STATE_NA_WRITE1;
			STATE_UPLOAD_DENIED: nextState = STATE_NA_WRITE1;
			STATE_UPLOAD_S5: nextState = (countReg == memorySize) ? STATE_UPLOAD_S7 : (memoryDataDone ? STATE_NA_WRITE_WORD1 : STATE_UPLOAD_S5);
			STATE_UPLOAD_S6: nextState = STATE_UPLOAD_S5;
			STATE_UPLOAD_S7: nextState = STATE_NA_READ1;
			STATE_UPLOAD_S8: nextState = STATE_NA_IDLE;
			STATE_BOARD_CONTROL_S1: nextState = STATE_NA_READ1;
			STATE_BOARD_CONTROL_S2: nextState = STATE_NA_WRITE1;
			STATE_BOARD_CONTROL_CHANGE_MODE1: nextState = STATE_NA_READ1;
			STATE_BOARD_CONTROL_CHANGE_MODE2: nextState = STATE_BOARD_CONTROL_CHANGE_MODE3;
			STATE_BOARD_CONTROL_CHANGE_MODE3: nextState = STATE_NA_WRITE1;
			STATE_BOARD_CONTROL_READ_MODE1: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_S1: nextState = STATE_NA_READ1;
			STATE_DEBUG1_S2: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_STEP1: nextState = STATE_NA_READ1;
			STATE_DEBUG1_STEP2: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_GET_PC1: nextState = STATE_NA_READ1;
			STATE_DEBUG1_GET_PC2: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_GET_PC3: nextState = STATE_NA_WRITE_WORD1;
			STATE_DEBUG1_GET_PC4: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_GET_REGFILE1: nextState = STATE_NA_READ1;
			STATE_DEBUG1_GET_REGFILE2: nextState = STATE_NA_WRITE1;
			STATE_DEBUG1_GET_REGFILE3: nextState = STATE_NA_WRITE_WORD1;
			STATE_DEBUG1_GET_REGFILE4: nextState = (countReg[4:0] == 5'd0) ? STATE_DEBUG1_GET_REGFILE5 : STATE_DEBUG1_GET_REGFILE3;
			STATE_DEBUG1_GET_REGFILE5: nextState = STATE_DEBUG1_GET_PC3;
			default: nextState = STATE_NA_IDLE;
		endcase
	 end
	 
	 reg dataInAckReg;
	 
	 
	 
	 
	 assign memoryDataOut = tempWord;
	 assign memoryAddress = {countReg[29:0], 2'b0};
	 
	 reg [7:0] dataOutReg;
	 reg dataOutReadyReg;
	 
	 
	 assign dataInAck = dataInAckReg;
	 assign dataOut = dataOutReg;
	 assign dataOutReady = dataOutReadyReg;
	 reg mode_override_enable_reg = 1'b0;
	 assign mode_override_enable = mode_override_enable_reg;
	 assign mode_override = tempReg[1:0];
	 
	 always @(posedge clk_50) begin
		stateAfterReg <= stateAfterReg;
		
		temp2Reg <= temp2Reg;
		tempReg <= tempReg;
		dataInAckReg <= dataInAckReg;
				
		dataOutReg <= dataOutReg;
		dataOutReadyReg <= dataOutReadyReg;
		tempWord <= tempWord;
		selectorReg <= selectorReg;
		countReg <= countReg;
		
		memorySize <= memorySize;
		writeMemReg <= writeMemReg;
		mode_override_enable_reg <= mode_override_enable_reg;
		cpuDebugClksReg <= cpuDebugClksReg;
		case(state)
			STATE_NA_IDLE: begin
				stateAfterReg <= STATE_NA_READ_OP1;
				
				temp2Reg <= 8'b0;
				tempReg <= 8'b0;
				dataInAckReg <= 0;
				dataOutReg <= 8'b0;
				dataOutReadyReg <= 0;
				tempWord <= 32'b0;
				selectorReg <= 4'b0;
				countReg <= 32'b0;
				memorySize <= 32'b0;
				writeMemReg <= 1'b0;
				mode_override_enable_reg <= 1'b0;
				end
			STATE_NA_READ1: begin
				dataInAckReg <= 0;
			end
			STATE_NA_READ2: begin
				dataInAckReg <= 1;
				tempReg <= dataIn;
			end
			STATE_NA_READ3: begin
				dataInAckReg <= 0;
			end
			STATE_NA_WRITE1: dataOutReadyReg <= 1;
			STATE_NA_WRITE2: dataOutReadyReg <= 0;
			STATE_NA_READ_OP1: begin end
			STATE_NA_READ_OP_SUPPORTED: begin
				dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
				stateAfterReg <= {tempReg[3:0], 4'b0};
			end
			STATE_NA_READ_OP_NOT_SUPPORTED: begin
				dataOutReg <= {4'b0, ~tempReg[7:4]};
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_UPCO_S1: begin
				dataOutReg <= {cpuCountBus, memCountBus};
				stateAfterReg <= STATE_UPCO_S2; // STATE_UPCO_S1;
				selectorReg <= 4'd0;
			end
			STATE_UPCO_S2: begin
				dataOutReg <= cpuStandardclk;
				stateAfterReg <= STATE_UPCO_S3;
				selectorReg <= selectorReg + 4'b1;
			end
			STATE_UPCO_S3: begin end
			STATE_UPCO_S4: selectorReg <= 4'd0;
			STATE_UPCO_S5: begin
				tempWord <= memorySelectedSize;
				stateAfterReg <= STATE_UPCO_S6;
				selectorReg <= selectorReg + 4'b1; 
			end
			STATE_UPCO_S6: begin end
			STATE_NA_WRITE_WORD1: begin
				tempReg <= stateAfterReg;
				stateAfterReg <= STATE_NA_WRITE_WORD2;
				dataOutReg <= tempWord[31:24];
			end
			STATE_NA_WRITE_WORD2: begin
				stateAfterReg <= STATE_NA_WRITE_WORD3;
				dataOutReg <= tempWord[23:16];
			end
			STATE_NA_WRITE_WORD3: begin
				stateAfterReg <= STATE_NA_WRITE_WORD4;
				dataOutReg <= tempWord[15:8];
			end
			STATE_NA_WRITE_WORD4: begin
				stateAfterReg <= tempReg;
				dataOutReg <= tempWord[7:0];
			end
			STATE_NA_READ_WORD1: begin //to use set temp2Reg to where you want to end up, stateAfterReg to this state and 
				tempWord[31:24] <= tempReg;
				stateAfterReg <= STATE_NA_READ_WORD2;
			end
			STATE_NA_READ_WORD2: begin
				tempWord[23:16] <= tempReg;
				stateAfterReg <= STATE_NA_READ_WORD3;
			end
			STATE_NA_READ_WORD3: begin
				tempWord[15:8] <= tempReg;
				stateAfterReg <= STATE_NA_READ_WORD4;
			end
			STATE_NA_READ_WORD4: begin
				tempWord[7:0] <= tempReg;
				//stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_DOWN_S1: begin
				stateAfterReg <= STATE_DOWN_S2;
			end
			STATE_DOWN_S2: begin
				selectorReg <= tempReg[3:0];
				temp2Reg <= STATE_DOWN_S3;
				stateAfterReg <= STATE_NA_READ_WORD1;
			end
			STATE_DOWN_S3: begin
				memorySize <= tempWord;
			end
			STATE_DOWN_ACCEPTED: begin
				dataOutReg <= ACCEPTED_BYTE;
				stateAfterReg <= STATE_DOWN_S4;
				countReg <= 32'd0;
			end
			STATE_DOWN_DENIED: begin
				dataOutReg <= DECLINED_BYTE;
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_DOWN_S4: begin
				stateAfterReg <= STATE_NA_READ_WORD1;
				temp2Reg <= STATE_DOWN_S5;
			end
			STATE_DOWN_S5: begin
				writeMemReg <= 1;
			end
			STATE_DOWN_S6: begin
				writeMemReg <= 1;
			end
			STATE_DOWN_S7: begin
				writeMemReg <= 0;
				countReg <= countReg + 1;
			end
			STATE_DOWN_S8: begin
				dataOutReg <= 8'b10101111;
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_UPLOAD_S1: begin
				stateAfterReg <= STATE_UPLOAD_S2;
			end
			STATE_UPLOAD_S2: begin
				selectorReg <= tempReg[3:0];
				temp2Reg <= STATE_UPLOAD_S3;
				stateAfterReg <= STATE_NA_READ_WORD1;
			end
			STATE_UPLOAD_S3: begin
				countReg <= tempWord;
				temp2Reg <= STATE_UPLOAD_S4;
				stateAfterReg <= STATE_NA_READ_WORD1;
			end
			STATE_UPLOAD_S4: begin
				memorySize <= countReg + tempWord;
			end
			STATE_UPLOAD_ACCEPTED: begin
				dataOutReg <= ACCEPTED_BYTE;
				stateAfterReg <= STATE_UPLOAD_S5;
			end
			STATE_UPLOAD_DENIED: begin
				dataOutReg <= DECLINED_BYTE;
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_UPLOAD_S5: begin
				tempWord <= memoryDataIn;
				stateAfterReg <= STATE_UPLOAD_S6;
			end
			STATE_UPLOAD_S6: begin
				countReg <= countReg + 1;
			end
			STATE_UPLOAD_S7: begin
				stateAfterReg <= STATE_UPLOAD_S8;
			end
			STATE_BOARD_CONTROL_S1: begin
				stateAfterReg <= STATE_BOARD_CONTROL_S2;
			end
			STATE_BOARD_CONTROL_S2: begin
				if(tempReg[3:0] == OP_BC_CHANGE_MODE) begin
					dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
					stateAfterReg <= STATE_BOARD_CONTROL_CHANGE_MODE1;
				end
				else if(tempReg[3:0] == OP_BC_READ_MODE) begin
					dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
					stateAfterReg <= STATE_BOARD_CONTROL_READ_MODE1;
				end
				else begin
					dataOutReg <= {4'b0,~tempReg[7:4]};
					stateAfterReg <= STATE_NA_IDLE;
				end
			end
			STATE_BOARD_CONTROL_CHANGE_MODE1: begin
				stateAfterReg <= STATE_BOARD_CONTROL_CHANGE_MODE2;
			end
			STATE_BOARD_CONTROL_CHANGE_MODE2: begin
				mode_override_enable_reg <= 1'b1;
			end
			STATE_BOARD_CONTROL_CHANGE_MODE3: begin
				mode_override_enable_reg <= 1'b0;
				dataOutReg <= ACCEPTED_BYTE;
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_BOARD_CONTROL_READ_MODE1: begin
				dataOutReg <= {4'hA, 2'd0, mode};
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_DEBUG1_S1: begin
				stateAfterReg <= STATE_DEBUG1_S2;
			end
			STATE_DEBUG1_S2: begin
				if(tempReg[3:0] == OP_DEBUG1_STEP) begin
					dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
					stateAfterReg <= STATE_DEBUG1_STEP1;
				end
				else if(tempReg[3:0] == OP_DEBUG1_GET_PC) begin
					dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
					stateAfterReg <= STATE_DEBUG1_GET_PC1;
				end
				else if(tempReg[3:0] == OP_DEBUG1_GET_REGFILE) begin
					dataOutReg <= {tempReg[3:0], ~tempReg[7:4]};
					stateAfterReg <= STATE_DEBUG1_GET_REGFILE1;
				end
				else begin
					dataOutReg <= {4'b0, ~tempReg[7:4]};
					stateAfterReg <= STATE_NA_IDLE;
				end
			end
			STATE_DEBUG1_STEP1: begin
				stateAfterReg <= STATE_DEBUG1_STEP2;
			end
			STATE_DEBUG1_STEP2: begin
				selectorReg <= tempReg[3:0];
				dataOutReg[7:4] <= (tempReg[3:0] < cpuCount) ? tempReg[3:0] : 4'b0;
				dataOutReg[3:0] <= ~tempReg[7:4];
				stateAfterReg <= STATE_NA_IDLE;
				case(tempReg[3:0])
					4'd0: cpuDebugClksReg[0] <= ~cpuDebugClksReg[0];
					4'd1: cpuDebugClksReg[1] <= ~cpuDebugClksReg[1];
					4'd2: cpuDebugClksReg[2] <= ~cpuDebugClksReg[2];
					4'd3: cpuDebugClksReg[3] <= ~cpuDebugClksReg[3];
					4'd4: cpuDebugClksReg[4] <= ~cpuDebugClksReg[4];
					4'd5: cpuDebugClksReg[5] <= ~cpuDebugClksReg[5];
					4'd6: cpuDebugClksReg[6] <= ~cpuDebugClksReg[6];
					4'd7: cpuDebugClksReg[7] <= ~cpuDebugClksReg[7];
					4'd8: cpuDebugClksReg[8] <= ~cpuDebugClksReg[8];
					4'd9: cpuDebugClksReg[9] <= ~cpuDebugClksReg[9];
					4'd10: cpuDebugClksReg[10] <= ~cpuDebugClksReg[10];
					4'd11: cpuDebugClksReg[11] <= ~cpuDebugClksReg[11];
					4'd12: cpuDebugClksReg[12] <= ~cpuDebugClksReg[12];
					4'd13: cpuDebugClksReg[13] <= ~cpuDebugClksReg[13];
					4'd14: cpuDebugClksReg[14] <= ~cpuDebugClksReg[14];
					4'd15: cpuDebugClksReg[15] <= ~cpuDebugClksReg[15];
				endcase
				//need to do some stuff here to get it to flip the correct clk signal
			end
			STATE_DEBUG1_GET_PC1: begin //go to reading byte (to know wich cpu to look at)
				stateAfterReg <= STATE_DEBUG1_GET_PC2;
			end
			STATE_DEBUG1_GET_PC2: begin
				selectorReg <= tempReg[3:0];
				dataOutReg[7:4] <= (tempReg[3:0] < cpuCount) ? tempReg[3:0] : 4'b0;
				dataOutReg[3:0] <= ~tempReg[7:4];
				stateAfterReg <= (tempReg[3:0] < cpuCount) ? STATE_DEBUG1_GET_PC3 : STATE_NA_IDLE;
			end
			STATE_DEBUG1_GET_PC3: begin
				tempWord <= cpuPC;
				stateAfterReg <= STATE_DEBUG1_GET_PC4;
			end
			STATE_DEBUG1_GET_PC4: begin
				dataOutReg <= ACCEPTED_BYTE;
				stateAfterReg <= STATE_NA_IDLE;
			end
			STATE_DEBUG1_GET_REGFILE1: begin
				stateAfterReg <= STATE_DEBUG1_GET_REGFILE2;
			end
			STATE_DEBUG1_GET_REGFILE2: begin
				selectorReg <= tempReg[3:0];
				dataOutReg[7:4] <= (tempReg[3:0] < cpuCount) ? tempReg[3:0] : 4'b0;
				dataOutReg[3:0] <= ~tempReg[7:4];
				stateAfterReg <= (tempReg[3:0] < cpuCount) ? STATE_DEBUG1_GET_REGFILE3 : STATE_NA_IDLE;
				countReg <= 32'd00;
			end
			STATE_DEBUG1_GET_REGFILE3: begin
				tempWord <= cpuRegisterValue;
				stateAfterReg <= STATE_DEBUG1_GET_REGFILE4;
				countReg[4:0] <= countReg[4:0] + 5'd1;
			end
			STATE_DEBUG1_GET_REGFILE4: begin
				
			end
			STATE_DEBUG1_GET_REGFILE5: begin
				countReg[4:0] <= 5'd0;
			end
		endcase
	 end

endmodule
